package com.xxx.system.service.impl;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xxx.base.exception.BusinessException;
import com.xxx.system.domain.Logininfo;
import com.xxx.system.domain.Menu;
import com.xxx.system.dto.LoginDTO;
import com.xxx.system.jwt.JwtUtil;
import com.xxx.system.jwt.Payload;
import com.xxx.system.mapper.LogininfoMapper;
import com.xxx.system.query.LogininfoQuery;
import com.xxx.system.service.ILogininfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
public class LogininfoServiceImpl implements ILogininfoService {

    @Autowired
    private LogininfoMapper logininfoMapper;

    @Override
    public List<Logininfo> findAll() {
        return logininfoMapper.findAll();
    }

    @Override
    public Logininfo findOne(Long id) {
        return logininfoMapper.findOne(id);
    }

    @Override
    @Transactional
    public void delete(Long id) {
        //删除角色
        logininfoMapper.delete(id);
    }

    @Override
    @Transactional
    public void add(Logininfo logininfo) {
        //添加角色信息
        logininfoMapper.add(logininfo); //自增id
    }

    @Override
    @Transactional
    public void update(Logininfo logininfo) {
        logininfoMapper.update(logininfo);
    }

    @Override
    public void patchDelete(Long[] ids) {
        logininfoMapper.patchDelete(ids);
    }

    @Override
    public PageInfo<Logininfo> queryPage(LogininfoQuery logininfoQuery) {
        //开启分页
        PageHelper.startPage(logininfoQuery.getCurrentPage(),logininfoQuery.getPageSize());
        List<Logininfo> data  = logininfoMapper.queryPage(logininfoQuery);
        return new PageInfo<>(data);
    }

    @Override
    public String login(LoginDTO loginDTO) {//前端传的
        String account = loginDTO.getAccount();
        String password = loginDTO.getPassword();
        Integer type = loginDTO.getType();

        if (StrUtil.isBlank(account)||StrUtil.isBlank(password)||type==null){
            throw new BusinessException("参数不能为空");
        }


        Logininfo logininfo = logininfoMapper.findLoginInfo(loginDTO);

        if (logininfo == null) {
            throw new BusinessException("账户不存在");
        }

        String passwordJm = SecureUtil.md5(loginDTO.getPassword() + logininfo.getSalt());//前端密码加盐得到加密后的结果

        if (!passwordJm.equals(logininfo.getPassword())){
            throw new BusinessException("密码不正确");
        }

        //登录成功产生令牌给前端
        Payload payload = new Payload();
        //数据脱敏↓
        logininfo.setSalt(null);
        logininfo.setPassword(null);
        payload.setLogininfo(logininfo);
        if (type==0){
            List<String> permissions=logininfoMapper.findPs(logininfo.getId());
            payload.setPermissions(permissions);
            List<Menu> menus=this.getMenuTree(logininfo.getId());
            payload.setMenus(menus);
        }

        String jwt = JwtUtil.generateToken(payload);

        return jwt;
    }

    private List<Menu> getMenuTree(Long id) {
        List<Menu> list=logininfoMapper.findMs(id);//员工id关联的菜单集合

        Map<Long, Menu> menuMap =
                list.stream().collect(
                        Collectors.toMap(Menu::getId, (d) -> d)
                );

        List<Menu> typeTree = new ArrayList<Menu>();
        
        for (Menu menu : list) {
            if (menu.getParentId() == null) {
                typeTree.add(menu);
            } else {//非顶级类型加入到父级类型下
                //找到父类型
                Menu parentMenu = menuMap.get(menu.getParentId());
                //添加自己到父类型的子类型集合中
                parentMenu.getChildren().add(menu);
            }
        }

        return typeTree;
    }
}
